#!/bin/sh

e2e_use_extensions() {
  true
}

e2e_test_install() {
  install_minio

  deploy_curl_pod "$CLUSTER_NAMESPACE"

  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" 2 \
    --set configurations.objectstorage.create=true \
    --set cluster.configurations.backups.sgObjectStorage="backupconf"

  OPERATOR_CLUSTER_CR="$(kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" -o json \
    | jq 'del(.metadata.creationTimestamp) | del(.metadata.generation) | del(.metadata.resourceVersion) | del(.metadata.selfLink) | del(.metadata.uid)' )"

  echo_raw "$OPERATOR_CLUSTER_CR" > "$LOG_PATH/stackgres-cluster-cr.json"

  OPERATOR_CLUSTER="$(cat "$LOG_PATH/stackgres-cluster-cr.json" \
    | jq 'del(.apiVersion) | del(.kind)' )"

  echo_raw "$OPERATOR_CLUSTER" > "$LOG_PATH/stackgres-cluster.json"

  NODE_LABEL_KEY="$(random_string)"
  NODE_LABEL_VALUE="$(random_string)"

  DUMMY_OPERATOR_CLUSTER="$(cat "$LOG_PATH/stackgres-cluster.json" \
    | jq ".spec.pods.scheduling={nodeSelector:{\"$NODE_LABEL_KEY\": \"$NODE_LABEL_VALUE\"}}" )"

  echo_raw "$DUMMY_OPERATOR_CLUSTER" > "$LOG_PATH/dummy-cluster.json"

  wait_pods_running "$CLUSTER_NAMESPACE" 4
  wait_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"
}

e2e_test() {
  run_test "Check that a created cluster can be accessed directly through the API" check_cluster_directly

  run_test "Check that the named queries endpoints are working correctly" test_named_queries_endpoints

  run_test "Check that a created cluster is included in the response" check_cluster_in_list

  run_test "Check that the stats endpoint are returning the primary stats" test_cluster_stats_are_loaded

  run_test "Check that the stats endpoint are returning when pods are ready" test_cluster_stats_pods_ready

  run_test "Check that the component versions are annotated" test_cluster_component_versions_are_annotated

  run_test "Check that the number of pods match with the primary and replicas" test_cluster_pod_count

  run_test "Check that a cluster was removed after its deletion in the API" check_cluster_removed

  run_test "Check cluster is created with the API and is visible in the API" test_api_created_cluster_is_visible

  run_test "Check cluster is updated with the API are reflected in the API" test_api_updated_cluster_is_visible

  run_test "Check cluster is deleted with the API are reflected in the API" test_api_delete_cluster_is_visible

  run_test "Check that when cluster is deleted with the API generated resources are also deleted" test_api_deleted_cluster_deletes_generated_resources

  run_test "Constraint violations should be detected" test_constraint_violation_api_error

  run_test "User with wrong credentials should not be authenticated" test_authentication_api_error

  run_test "Create cluster with inline scripts" check_create_cluster_with_inline_script

  run_test "Create cluster with node selectors" check_create_cluster_node_selectors_script

  run_test "Create cluster with secret and configmap scripts" check_create_cluster_with_secret_and_configmap_script

  run_test "Check extension validation returns error correcly if extension does not exists" check_extension_validation
}

check_cluster_in_list() {
  if run_curl -r "stackgres/sgclusters" \
    | jq -r ".[] | select ( .metadata.namespace == \"$CLUSTER_NAMESPACE\" and .metadata.name == \"$CLUSTER_NAME\") | .metadata.name" \
    | grep -q "^$CLUSTER_NAME$"
  then
    echo "Cluster $CLUSTER_NAME included in json response"
    return 0
  else
    echo "Cluster $CLUSTER_NAME not included in json response"
    return 1
  fi
}

get_cluster_from_api() {
  run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME"
}

get_cluster_http_status() {
  run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME" -e "-LI -o /dev/null -w %{http_code}"
}

get_cluster_stats_http_status() {
  run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME/stats" -e "-LI -o /dev/null -w %{http_code}"
}

get_cluster_pod_count() {
  run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME" | jq '.pods | length'
}

get_cluster_stats_pods_ready() {
  run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME-stats/stats" \
    | jq -r 'if .podsReady != null then .podsReady else 0 end'
}

check_cluster_directly() {
  local HTTP_STATUS

  HTTP_STATUS="$(get_cluster_http_status)"

  if [ "$HTTP_STATUS" -eq "200" ]
  then
    echo "Cluster $CLUSTER_NAME was found bye the api"
    return 0
  else
    echo "Cluster $CLUSTER_NAME was not found bye the api"
    return 1
  fi
}

get_named_query_results() {
  run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME/query?named=$1" \
    | jq -r '(.[0] | has("fields")) and ((. | length) == 1 or (.[1] | length) == (.[0].fields | length))' \
    | grep -qxF "true"
}

test_named_queries_endpoints() {
  # top_pg_stat_statements query
  if wait_until get_named_query_results top_pg_stat_statements
  then
    echo "Named query top_pg_stat_statements worked"
  else
    echo "Named query top_pg_stat_statements didn't worked"
    return 1
  fi

  # top_pg_stat_activity query
  if wait_until get_named_query_results top_pg_stat_activity
  then
    echo "Named query top_pg_stat_activity worked"
  else
    echo "Named query top_pg_stat_activity didn't worked"
    return 1
  fi

  # top_pg_locks query
  if wait_until get_named_query_results top_pg_locks
  then
    echo "Named query top_pg_locks worked"
  else
    echo "Named query top_pg_locks didn't worked"
    return 1
  fi
}

test_cluster_stats_are_loaded() {
  local HTTP_STATUS

  HTTP_STATUS="$(get_cluster_stats_http_status)"

  if [ "$HTTP_STATUS" -eq "200" ]
  then
    echo "Cluster $CLUSTER_NAME stats was found by the api"
  else
    echo "Cluster $CLUSTER_NAME stats was not found by the api"
    return 1
  fi

  local STATUS_RESPONSE
  STATUS_RESPONSE="$(run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME/stats")"

  if [ "$(echo_raw "$STATUS_RESPONSE" \
    | jq 'select(.cpuFound != null and .memoryUsed != null and .diskUsed != null and .averageLoad1m != null)' \
    | jq 'select(.pods[0].cpuFound != null and .pods[0].memoryUsed != null and .pods[0].diskUsed != null and .pods[0].averageLoad1m != null)' \
    | wc -l)" -ne 0 ]
  then
    echo "Cluster $CLUSTER_NAME stats was returned by the api"
  else
    echo "Cluster $CLUSTER_NAME stats was not returned by the api"
    return 1
  fi
}

test_cluster_stats_pods_ready() {
  create_or_replace_cluster "$CLUSTER_NAME-stats" "$CLUSTER_NAMESPACE-stats" 1 \
    --set configurations.objectstorage.create=false \
    --set cluster.configurations.backups.sgObjectStorage=null

  if ! wait_until -t 60 eval '[ "$(get_cluster_stats_pods_ready)" -eq 1 ]'
  then
    echo "Cluster $CLUSTER_NAME stats are ready"
  else
    echo "Cluster $CLUSTER_NAME stats are not ready"
    return 1
  fi
}

test_cluster_component_versions_are_annotated() {
  local POSTGRESQL_VERSION
  local PATRONI_VERSION
  local ENVOY_VERSION
  local PGBOUNCER_VERSION
  local PROMETHEUS_POSTGRES_EXPORTER_VERSION
  POSTGRESQL_VERSION="$(get_component_versions "$STACKGRES_VERSION" "postgresql" | grep -F "$E2E_POSTGRES_VERSION" | tail -n 1)"
  POSTGRESQL_VERSION="${POSTGRESQL_VERSION%-build-*}"
  PATRONI_VERSION="$(get_component_versions "$STACKGRES_VERSION" "patroni" | tail -n 1)"
  PATRONI_VERSION="${PATRONI_VERSION%-build-*}"
  ENVOY_VERSION="$(get_component_versions "$STACKGRES_VERSION" "envoy" | tail -n 1)"
  ENVOY_VERSION="${ENVOY_VERSION%-build-*}"
  PGBOUNCER_VERSION="$(get_component_versions "$STACKGRES_VERSION" "pgbouncer" | tail -n 1)"
  PGBOUNCER_VERSION="${PGBOUNCER_VERSION%-build-*}"
  PROMETHEUS_POSTGRES_EXPORTER_VERSION="$(get_component_versions "$STACKGRES_VERSION" "prometheus-postgres-exporter" | tail -n 1)"
  PROMETHEUS_POSTGRES_EXPORTER_VERSION="${PROMETHEUS_POSTGRES_EXPORTER_VERSION%-build-*}"

  for POD in "$CLUSTER_NAME-0" "$CLUSTER_NAME-1"
  do
    if [ "$(kubectl get pod -n "$CLUSTER_NAMESPACE" "$POD" -o jsonpath="{.metadata.annotations['stackgres\.io/postgresql-version']}")" = "$POSTGRESQL_VERSION" ]
    then
      success "Version of component 'postgresql' is $POSTGRESQL_VERSION for por $POD"
    else
      echo "FALIURE. Version of component 'postgresql' is not $POSTGRESQL_VERSION for por $POD"
      return 1
    fi

    if [ "$(kubectl get pod -n "$CLUSTER_NAMESPACE" "$POD" -o jsonpath="{.metadata.annotations['stackgres\.io/patroni-version']}")" = "$PATRONI_VERSION" ]
    then
      success "Version of component 'patroni' is $PATRONI_VERSION for por $POD"
    else
      echo "FALIURE. Version of component 'patroni' is not $PATRONI_VERSION for por $POD"
      return 1
    fi

    if ! kubectl get sgcluster -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" --template '{{ .spec.pods.disableEnvoy }}' | grep -qxF true
    then
      if [ "$(kubectl get pod -n "$CLUSTER_NAMESPACE" "$POD" -o jsonpath="{.metadata.annotations['stackgres\.io/envoy-version']}")" = "$ENVOY_VERSION" ]
      then
        success "Version of component 'envoy' is $ENVOY_VERSION for por $POD"
      else
        echo "FALIURE. Version of component 'envoy' is not $ENVOY_VERSION for por $POD"
        return 1
      fi
    fi

    if [ "$(kubectl get pod -n "$CLUSTER_NAMESPACE" "$POD" -o jsonpath="{.metadata.annotations['stackgres\.io/pgbouncer-version']}")" = "$PGBOUNCER_VERSION" ]
    then
      success "Version of component 'pgbouncer' is $PGBOUNCER_VERSION for por $POD"
    else
      echo "FALIURE. Version of component 'pgbouncer' is not $PGBOUNCER_VERSION for por $POD"
      return 1
    fi

    if [ "$(kubectl get pod -n "$CLUSTER_NAMESPACE" "$POD" -o jsonpath="{.metadata.annotations['stackgres\.io/prometheus-postgres-exporter-version']}")" = "$PROMETHEUS_POSTGRES_EXPORTER_VERSION" ]
    then
      success "Version of component 'prometheus-postgres-exporter' is $PROMETHEUS_POSTGRES_EXPORTER_VERSION for por $POD"
    else
      echo "FALIURE. Version of component 'prometheus-postgres-exporter' is not $PROMETHEUS_POSTGRES_EXPORTER_VERSION for por $POD"
      return 1
    fi
  done
}

test_cluster_pod_count() {
  BACKUP_NAME="$(get_sgbackup_name "${CLUSTER_NAME}-0-$(shuf -i 0-65535 -n 1)")"

    cat << EOF | kubectl create -f -
  apiVersion: stackgres.io/v1
  kind: SGBackup
  metadata:
    namespace: "$CLUSTER_NAMESPACE"
    name: "$BACKUP_NAME"
  spec:
    sgCluster: "$CLUSTER_NAME"
    managedLifecycle: false
EOF

  if ! wait_until -t 60 eval '[ "$(get_cluster_pod_count)" -ne 2 ]'
  then
    echo "Good. User initiated backups didn't appear as cluster pods"
  else
    echo "Pods in cluster should be 2. User initiated backups could have being shown as cluster pods"
    return 1
  fi

  kubectl delete sgbackup -n "$CLUSTER_NAMESPACE" "$BACKUP_NAME"
}

remove_cluster_cr_if_exists() {
  if kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" >/dev/null 2>&1
  then
    kubectl delete sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME"

    wait_until eval '! kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME"'
  fi
}

check_cluster_removed() {
  local HTTP_STATUS

  remove_cluster_cr_if_exists

  if run_curl -r "stackgres/sgclusters" \
    | jq -r ".[] | select ( .metadata.namespace == \"$CLUSTER_NAMESPACE\" and .metadata.name == \"$CLUSTER_NAME\") | .metadata.name" \
    | grep -q "^$CLUSTER_NAME$"
  then
    echo "Cluster $CLUSTER_NAME wasn't removed from cache"
    return 1
  else
    echo "Cluster $CLUSTER_NAME was removed from cache"
    return 0
  fi

  HTTP_STATUS="$(run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME" -e "-LI -o /dev/null -w %{http_code}")"

  if [ "$HTTP_STATUS" -eq "404" ]
  then
    echo "Cluster $CLUSTER_NAME was not found by the api"
    return 0
  else
    echo "Cluster $CLUSTER_NAME was found by the api"
    return 1
  fi
}

create_cluster_with_api() {
  local CLUSTER_FILE="${1:-"$LOG_PATH/stackgres-cluster.json"}"
  local HTTP_STATUS

  remove_cluster_cr_if_exists

  HTTP_STATUS="$(run_curl -r "stackgres/sgclusters" -d "$CLUSTER_FILE" -e '-X POST -w %{http_code} -o /dev/null')"

  if [ "$HTTP_STATUS" = "200" ] || [ "$HTTP_STATUS" = "202" ] || [ "$HTTP_STATUS" = "204" ]
  then
    echo "Request acknowledged by the operator"
    return 0
  else
    ERROR_RESPONSE="$(run_curl -r "stackgres/sgclusters" -d "$CLUSTER_FILE" -e '-X POST')"
    echo "Invalid response status $HTTP_STATUS. response: $ERROR_RESPONSE"
    return 1
  fi
}

test_api_created_cluster_is_visible() {
  create_cluster_with_api "$LOG_PATH/dummy-cluster.json"

  if kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME"
  then
    echo "Cluster created with the API"
  else
    echo "Cluster CR was not created"
    return 1
  fi

  check_cluster_directly
}

update_cluster_parameter_with_api() {
  local HTTP_STATUS

  UPDATED_STACKGRES_CLUSTER="$(kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" -o json \
    | jq 'del(.metadata.creationTimestamp) | del(.metadata.generation) | del(.metadata.resourceVersion) | del(.metadata.selfLink) | del(.metadata.uid)' \
    | jq ".spec[\"$1\"] = $2" )"

  echo_raw "$UPDATED_STACKGRES_CLUSTER" > "$LOG_PATH/updated-stackgres-cluster.json"

  HTTP_STATUS="$(run_curl -r "stackgres/sgclusters" -d "$LOG_PATH/updated-stackgres-cluster.json" -e '-X PUT -w %{http_code} -o /dev/null')"

  if [ "$HTTP_STATUS" = "200" ] || [ "$HTTP_STATUS" = "202" ] || [ "$HTTP_STATUS" = "204" ]
  then
    echo "Request acknowledged by the operator"
    return 0
  else
    ERROR_RESPONSE="$(run_curl -r "stackgres/sgclusters" -d "$LOG_PATH/updated-stackgres-cluster.json" -e '-X PUT')"
    echo "Invalid response status $HTTP_STATUS. response: $ERROR_RESPONSE"
    return 1
  fi
}

test_api_updated_cluster_is_visible() {
  update_cluster_parameter_with_api 'instances' '2'

  if kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" -o jsonpath='{.spec.instances}' \
    | grep -q "^2$"
  then
    echo "Cluster instances were increased"
  else
    echo "Cluster instances weren't increase"
    return 1
  fi

  if run_curl -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME" | jq '.spec.instances' -r \
    | grep -q "^2$"
  then
    echo "Cluster updates are being reflected in the api"
  else
    echo "Cluster updates aren't being reflected in the api"
    return 1
  fi
}

delete_cluster_with_api() {
  local HTTP_STATUS

  HTTP_STATUS="$(run_curl -r "stackgres/sgclusters" -d "$LOG_PATH/stackgres-cluster.json" -e '-X DELETE -w %{http_code} -o /dev/null')"

  if [ "$HTTP_STATUS" = "200" ] || [ "$HTTP_STATUS" = "202" ] || [ "$HTTP_STATUS" = "204" ]
  then
    echo "Request acknowledged by the operator"
    return 0
  else
    ERROR_RESPONSE="$(run_curl -r "stackgres/sgclusters" -d "$LOG_PATH/stackgres-cluster.json" -e '-X PUT')"
    echo "Invalid response status $HTTP_STATUS. response: $ERROR_RESPONSE"
    return 1
  fi
}

test_api_delete_cluster_is_visible() {
  delete_cluster_with_api

  if wait_until eval '[ "$(get_cluster_http_status)" = "404" ]'
  then
    echo "Cluster removed from the API"
  else
    echo "Cluster wasn't removed from the API"
    return 1
  fi
}

test_api_deleted_cluster_deletes_generated_resources() {
  if wait_until has_no_cluster_generated_resources
  then
    echo "Cluster resources where removed"
  else
    echo "Cluster resources wheren't removed"
    return 1
  fi
}

has_no_cluster_generated_resources() {
  ! kubectl get sts -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME"
}

test_constraint_violation_api_error() {
  INVALID_CLUSTER="$(cat "$LOG_PATH/dummy-cluster.json" | jq '.spec.instances = -1' )"

  echo "$INVALID_CLUSTER" > "$LOG_PATH/invalid-cluster.json"

  local HTTP_STATUS

  HTTP_STATUS="$(run_curl -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE"  -d "$LOG_PATH/invalid-cluster.json" -e '-X POST -w %{http_code} -o /dev/null')"

  assert_string_equal "422" "$HTTP_STATUS"

  ERROR_RESPONSE="$(run_curl -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE" -d "$LOG_PATH/invalid-cluster.json" -e '-X POST')"

  EXPECTED_ERROR_TYPE="constraint-violation"
  EXPECTED_ERROR_TITLE="do not comply with the syntactic rules"
  EXPECTED_ERROR_DETAIL="spec.instances in body should be greater than or equal to 0"
  EXPECTED_ERROR_FIELD="instances"

  assert_api_error "$ERROR_RESPONSE"

  INVALID_CLUSTER_NAME="$(cat "$LOG_PATH/dummy-cluster.json" | jq '.metadata.name = "test-pg12.8"' )"

  echo "$INVALID_CLUSTER_NAME" > "$LOG_PATH/invalid-cluster-name.json"

  local HTTP_STATUS

  HTTP_STATUS="$(run_curl -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE"  -d "$LOG_PATH/invalid-cluster-name.json" -e '-X POST -w %{http_code} -o /dev/null')"

  assert_string_equal "422" "$HTTP_STATUS"

  ERROR_RESPONSE="$(run_curl -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE" -d "$LOG_PATH/invalid-cluster-name.json" -e '-X POST')"

  EXPECTED_ERROR_TYPE="constraint-violation"
  EXPECTED_ERROR_TITLE="Some fields do not comply with the syntactic rules"
  EXPECTED_ERROR_DETAIL="metadata.name in body should match '^[a-z]([-a-z0-9]*[a-z0-9])?$'"
  EXPECTED_ERROR_FIELD="metadata.name"

  assert_api_error "$ERROR_RESPONSE"
}

test_authentication_api_error() {
  local HTTP_STATUS

  HTTP_STATUS="$(run_curl -j "$FAKE_JWT" -r "stackgres/sgclusters"  -n "$CLUSTER_NAMESPACE" -e "-LI -o /dev/null -w %{http_code}")"

  check_authentication_error

  HTTP_STATUS="$(run_curl -j "$FAKE_JWT" -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME" -n "$CLUSTER_NAMESPACE" -e "-LI -o /dev/null -w %{http_code}")"

  check_authentication_error

  HTTP_STATUS="$(run_curl -j "$FAKE_JWT" -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME/stats" -n "$CLUSTER_NAMESPACE" -e "-LI -o /dev/null -w %{http_code}")"

  check_authentication_error

  HTTP_STATUS="$(run_curl -j "$FAKE_JWT" -r "stackgres/namespaces/$CLUSTER_NAMESPACE/sgclusters/$CLUSTER_NAME/logs" -n "$CLUSTER_NAMESPACE" -e "-LI -o /dev/null -w %{http_code}")"

  check_authentication_error

  HTTP_STATUS="$(run_curl -j "$FAKE_JWT" -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE" -d "$LOG_PATH/dummy-cluster.json" -e '-X POST -w %{http_code} -o /dev/null')"

  check_authentication_error

  HTTP_STATUS="$(run_curl -j "$FAKE_JWT" -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE" -d "$LOG_PATH/dummy-cluster.json" -e '-X PUT -w %{http_code} -o /dev/null')"

  check_authentication_error

  HTTP_STATUS="$(run_curl -j "$FAKE_JWT" -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE" -d "$LOG_PATH/dummy-cluster.json" -e '-X DELETE -w %{http_code} -o /dev/null')"

  check_authentication_error
}

check_authentication_error() {
  if [ "$HTTP_STATUS" = "401" ]
  then
    echo "Request returned expected authentication error"
    return 0
  else
    echo "Request returned unexpected response status $HTTP_STATUS instead of the expected authentication error."
    return 1
  fi
}

check_create_cluster_with_inline_script() {
  remove_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"

  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" 2 \
    --set configurations.objectstorage.create=true \
    --set cluster.configurations.backups.sgObjectStorage="backupconf"

  OPERATOR_CLUSTER_CR="$(kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" -o json \
    | jq 'del(.metadata.creationTimestamp) | del(.metadata.generation) | del(.metadata.resourceVersion) | del(.metadata.selfLink) | del(.metadata.uid)' \
    | jq '.spec.managedSql={}' | jq '.spec.managedSql.scripts=[]' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].name = "init"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].script = "CREATE DATABASE test"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].name = "table"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].database = "test"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].script = "CREATE TABLE fibonacci(num integer)"')"

  echo_raw "$OPERATOR_CLUSTER_CR" > "$LOG_PATH/inline-scripts-cluster.json"

  create_cluster_with_api "$LOG_PATH/inline-scripts-cluster.json"

  if [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[0].name}")" = "init" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[0].database}")" = "" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[0].script}")" = "CREATE DATABASE test" ]
  then
    success "Init inline script was added to cluster configuration"
  else
    fail "Init inline script was NOT added to cluster configuration"
  fi

  if [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[1].name}")" = "table" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[1].database}")" = "test" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[1].script}")" = "CREATE TABLE fibonacci(num integer)" ]
  then
    success "Table inline script was added to cluster configuration"
  else
    fail "Table inline script was NOT added to cluster configuration"
  fi

  OPERATOR_CLUSTER="$(get_cluster_from_api)"

  if [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].name')" = "init" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].database')" = "null" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].script')" = "CREATE DATABASE test" ]
  then
    success "Init inline script was added to cluster configuration"
  else
    fail "Init inline script was NOT added to cluster configuration"
  fi

  if [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].name')" = "table" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].database')" = "test" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].script')" = "CREATE TABLE fibonacci(num integer)" ]
  then
    success "Table inline script was added to script configuration"
  else
    fail "Table inline script was NOT added to script configuration"
  fi
}

check_create_cluster_with_secret_and_configmap_script() {
  remove_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"

  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" 2 \
    --set configurations.objectstorage.create=true \
    --set cluster.configurations.backups.sgObjectStorage="backupconf"

  OPERATOR_CLUSTER_CR="$(kubectl get sgclusters.stackgres.io -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" -o json \
    | jq 'del(.metadata.creationTimestamp) | del(.metadata.generation) | del(.metadata.resourceVersion) | del(.metadata.selfLink) | del(.metadata.uid)' \
    | jq 'del(.status)' \
    | jq '.spec.managedSql={}' | jq '.spec.managedSql.scripts=[]' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].name = "init"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].scriptFrom={}' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].scriptFrom.secretScript = "CREATE DATABASE test"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].scriptFrom.secretKeyRef = {}' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].scriptFrom.secretKeyRef.name = "init-script"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[0].scriptFrom.secretKeyRef.key = "script"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].name = "table"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].database = "test"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].scriptFrom={}' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].scriptFrom.configMapScript = "CREATE TABLE fibonacci(num integer)"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].scriptFrom.configMapKeyRef = {}' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].scriptFrom.configMapKeyRef.name = "table-script"' \
    | jq '.spec.managedSql.scripts[0].scriptSpec.scripts[1].scriptFrom.configMapKeyRef.key = "script"')"

  echo_raw "$OPERATOR_CLUSTER_CR" > "$LOG_PATH/secret-and-configmap-scripts-cluster.json"

  create_cluster_with_api "$LOG_PATH/secret-and-configmap-scripts-cluster.json"

  if [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[0].name}")" = "init" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[0].database}")" = "" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[0].scriptFrom.secretKeyRef.name}")" = "init-script" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[0].scriptFrom.secretKeyRef.key}")" = "script" ]
  then
    success "Secret script was added to cluster configuration"
  else
    fail "Secret script was NOT added to cluster configuration"
  fi

  if [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[1].name}")" = "table" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[1].database}")" = "test" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[1].scriptFrom.configMapKeyRef.name}")" = "table-script" ] \
    && [ "$(kubectl get sgscript -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-managed-sql-0" \
    -o jsonpath="{.spec.scripts[1].scriptFrom.configMapKeyRef.key}")" = "script" ]
  then
    success "ConfigMap script was added to cluster configuration"
  else
    fail "ConfigMap script was NOT added to cluster configuration"
  fi

  OPERATOR_CLUSTER="$(get_cluster_from_api)"

  if [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].name')" = "init" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].database')" = "null" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].scriptFrom.secretKeyRef.name')" = "init-script" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].scriptFrom.secretKeyRef.key')" = "script" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[0].scriptFrom.secretScript')" = "null" ]
  then
    success "Secret script was added to cluster configuration"
  else
    fail "Secret script was NOT added to cluster configuration"
  fi

  if [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].name')" = "table" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].database')" = "test" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].scriptFrom.configMapKeyRef.name')" = "table-script" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].scriptFrom.configMapKeyRef.key')" = "script" ] \
    && [ "$(echo true | jq -r --arg cluster "$OPERATOR_CLUSTER" \
        '$cluster | fromjson | .spec.managedSql.scripts[1].scriptSpec.scripts[1].scriptFrom.configMapScript')" = "CREATE TABLE fibonacci(num integer)" ]
  then
    success "ConfigMap script was added to script configuration"
  else
    fail "ConfigMap script was NOT added to script configuration"
  fi

  kubectl delete secret -n "$CLUSTER_NAMESPACE" "init-script" > /dev/null

  kubectl delete configmap -n "$CLUSTER_NAMESPACE" "table-script" > /dev/null
}

check_create_cluster_node_selectors_script() {
  NODE_LABEL_KEY="$(random_string)"
  NODE_LABEL_VALUE="$(random_string)"

  OPERATOR_CLUSTER_CR="$(cat "$LOG_PATH/stackgres-cluster.json" \
    | jq 'del(.metadata.creationTimestamp) | del(.metadata.generation) | del(.metadata.resourceVersion) | del(.metadata.selfLink) | del(.metadata.uid)' \
    | jq '.spec.pods.scheduling={}' | jq '.spec.pods.scheduling.nodeSelector={}' \
    | jq '.spec.pods.scheduling.nodeSelector["'"$NODE_LABEL_KEY"'"] = "'"$NODE_LABEL_VALUE"'"')"

  echo_raw "$OPERATOR_CLUSTER_CR" > "$LOG_PATH/node-selector-cluster.json"

  create_cluster_with_api "$LOG_PATH/node-selector-cluster.json"

  ACTUAL_NODE_VALUE="$(kubectl get sgcluster -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" \
    -o jsonpath='{.spec.pods.scheduling.nodeSelector.'"$NODE_LABEL_KEY"'}')"

  assert_string_equal "$NODE_LABEL_VALUE" "$ACTUAL_NODE_VALUE"
}

check_extension_validation() {
  INVALID_CLUSTER="$(cat "$LOG_PATH/dummy-cluster.json" | jq '.spec.postgres.extensions = [{name: "non-existing-extension"}]')"

  echo "$INVALID_CLUSTER" > "$LOG_PATH/invalid-extension-cluster.json"

  local HTTP_STATUS

  HTTP_STATUS="$(run_curl -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE"  -d "$LOG_PATH/invalid-extension-cluster.json" -e '-X POST -w %{http_code} -o /dev/null')"

  assert_string_equal "400" "$HTTP_STATUS"

  ERROR_RESPONSE="$(run_curl -r "stackgres/sgclusters" -n "$CLUSTER_NAMESPACE" -d "$LOG_PATH/invalid-extension-cluster.json" -e '-X POST')"

  EXPECTED_ERROR_TYPE="extension-not-found"
  EXPECTED_ERROR_TITLE="Extension not found"
  EXPECTED_ERROR_DETAIL="Extension was not found: non-existing-extension"
  EXPECTED_ERROR_FIELD=""

  assert_api_error "$ERROR_RESPONSE"
}
